import {
  type SignParams,
  fetchOssSign,
  type OssSignResult,
  fetchCheckOssFile,
} from "@/api/upload";
import { FILE_TYPE } from "@/utils/enums";
import { ref } from "vue";

export interface FileContent {
  name: string;
  size: number;
  thumb: string;
  type: keyof typeof FILE_TYPE;
  url: string;
}

export interface UploadEvent {
  file: FileContent[];
  index: number;
  name: string;
}

/** oss已经创建了文件名的文件列表 */
export interface MkdirFile {
  name: string;
  progress: number;
  url?: string;
  status: string;
  message: string;
}
export const mkdirFileList = ref<MkdirFile[]>([]);

export const useUpload = (fileJob = "article", limit = 1) => {
  /** 通过后端签名获取需要上传的文件名 */
  const getOssSignFile = async (params: SignParams) => {
    const { data: ossSignResult } = await fetchOssSign(params);
    return ossSignResult;
  };
  /** 将上传组件的文件转化为对应的Blob,并且推送流到对应的oss文件里 */
  const fileContentToOss = async (
    files: FileContent[],
    ossSignResult: OssSignResult,
  ) => {
    const uploadRequests = [];
    for (const [index, file] of files.entries()) {
      /** 根据上传的文件数据获取对应的arraybuffer */
      const { data: imgArrayBuffer } = await uni.request({
        method: "GET",
        url: file.url,
        responseType: "arraybuffer",
      });

      const fetchUploadFile = uni.request({
        url: ossSignResult.sign.signUrl[index],
        data: imgArrayBuffer,
        method: "PUT",
        header: {
          // #ifdef H5
          "Content-Type": "",
          // #endif
          // #ifndef H5
          "content-type": " ",
          // #endif
        },
      });

      uploadRequests.push(fetchUploadFile);
    }
    return uploadRequests;
  };
  /** 对上传成功的文件进行审查,并筛选出mkdirFileList已成功的 */
  const checkOssFile = async (
    uploadResult: PromiseSettledResult<UniApp.RequestSuccessCallbackResult>[],
  ) => {
    const successPromise = [];
    for (const [index, res] of uploadResult.entries()) {
      if (res.status === "fulfilled" && res.value.statusCode === 200)
        successPromise.push(res);
      else mkdirFileList.value[index].status = "failed";
    }
    const params = {
      object: mkdirFileList.value.map((file) => file.name).join(","),
    };
    const {
      data: { object },
    }: { data: { object: string[] } } = await fetchCheckOssFile(params);

    return object;
  };
  /** 设置当前文件正在上传的文件列表 */
  const setMkdirFileList = (data: OssSignResult["sign"]["object"]) => {
    if (limit === 1) mkdirFileList.value = [];
    data.forEach((fileName) =>
      mkdirFileList.value.push({
        name: fileName,
        progress: 0,
        status: "uploading",
        message: "上传中",
      }),
    );
  };
  /** 上传文件钩子 */
  const handleUpload = async (event: UploadEvent) => {
    const fileType = event.file[0]?.type;

    let fileNames: string;
    // #ifdef H5
    fileNames = event.file.map((file) => file.name).join(",");
    // #endif
    // #ifndef H5
    fileNames = event.file.map((file) => file.url.split("/").pop()).join(",");
    // #endif
    const signParams: SignParams = {
      fileType: FILE_TYPE[fileType] || FILE_TYPE.image,
      type: fileJob,
      method: "PUT" as const,
      fileName: fileNames,
    };

    const ossSignResult = await getOssSignFile(signParams);

    // #region 把已通过oss创建好的文件存起来
    setMkdirFileList(ossSignResult.sign.object);
    // #endregion

    const uploadRequests = await fileContentToOss(event.file, ossSignResult);
    const uploadResult = await Promise.allSettled(uploadRequests);

    const object = await checkOssFile(uploadResult);

    mkdirFileList.value.forEach((mkdirFile) => {
      if (object.includes(mkdirFile.name)) {
        mkdirFile.progress = 100;
        mkdirFile.status = "success";
        mkdirFile.url = import.meta.env.VITE_API_IMG_URL + mkdirFile.name;
      } else {
        mkdirFile.status = "failed";
      }
    });
  };

  /** 超出大小文件提示 */
  const oversizeTip = () => {
    console.log("oversizeTip");
  };

  return {
    handleUpload,
    oversizeTip,
  };
};
